/*
 * MacCrypto.c
 *
 *  Created on: 2023年7月20日
 *      Author: fjx
 */
#include "bsp_aes_ccm.h"
#include "bsp_aes.h"
#include "RBFKeyNvm.h"
#include "app_log.h"
#include "MacCrypto.h"
#include "device.h"

/*
 *
 *
 */



#if defined (CONFIG_LOG_MACCRYPTO)
void RBF_aes_param_log (uint8_t * nonce, uint8_t *ad ,uint8_t plain_txt_len)
{
  DS_app_log_hexdump_debug("nonce data:",nonce,RBF_NONCE_LENGTH_MAX);
  DS_app_log_hexdump_debug("ad data:",ad,RBF_AD_LENGTH_MAX);
  DS_app_log_info("txt len = %d\n\n",plain_txt_len);
}
#endif


/*
 *
 */
SecureElementStatus_t RBF_aes_ae(KeyIdentifier_t identifier,
                                 const uint8_t *plaintext,
                                 size_t plaintext_length,
                                 uint8_t *ciphertext,
                                 size_t ciphertext_size,
                                 size_t *ciphertext_length )
{

  uint32_t key_id = 0;
  uint8_t _key[RBF_KEY_LENGTH_MAX]={0};

  switch(identifier){
    case KEY_ID_CODEAB:
      RBF_get_data_codeAB(_key);  //获取codeAB
      break;
    case KEY_ID_NVM_KEY:
      RBF_get_data_nvmKey(_key);
      break;
//    case KEY_ID_NVM_KEY_EN_KEY:
//
//      break;
    default:

      DS_app_log_info("AES key not supported!!\n");
      return SECURE_ELEMENT_ERROR_NOT_SUPPORTED;
  }

  DS_aes_init(_key,RBF_KEY_LENGTH_MAX);


  //获取key_id
//  if( RBF_get_key_id (identifier,&key_id) != SECURE_ELEMENT_SUCCESS){
//      return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
//  }
  key_id = DS_aes_get_key_id();

  DS_aes_use_keyid_ae(key_id,
                               plaintext,
                               plaintext_length,
                               ciphertext,
                               ciphertext_size,
                               ciphertext_length );

  return SECURE_ELEMENT_SUCCESS;
}
SecureElementStatus_t RBF_aes_de(KeyIdentifier_t identifier,
                                 uint8_t *ciphertext,
                                 size_t ciphertext_size,
                                 uint8_t *plaintext,
                                 size_t plaintext_length,
                                 size_t *ciphertext_length
                                 )
{
  uint32_t key_id = 0;
  uint8_t _key[RBF_KEY_LENGTH_MAX]={0};


  switch(identifier){
    case KEY_ID_CODEAB:
      RBF_get_data_codeAB(_key);  //获取codeAB
      break;
    case KEY_ID_NVM_KEY:
      RBF_get_data_nvmKey(_key);
      break;
//    case KEY_ID_NVM_KEY_EN_KEY:
//
//      break;
    default:

      printf("AES key not supported!!\n");
      return SECURE_ELEMENT_ERROR_NOT_SUPPORTED;
  }

  DS_aes_init(_key,RBF_KEY_LENGTH_MAX);
  //获取key_id
  key_id = DS_aes_get_key_id();

  if(DS_aes_use_keyid_de(key_id,
                               ciphertext,
                               ciphertext_size,
                               plaintext,
                               plaintext_length,
                               ciphertext_length) != 0){

      return SECURE_ELEMENT_FAIL_CCM;
  }

  return SECURE_ELEMENT_SUCCESS;
}

/*
 *@param  packet 为mac原始输入数据，包含数据长度、header、payload.
 *@param  len packet数据长度 TODO:len参数是否存在多余,协议packet[0]表示数据长度
 *@param  identifier key的类型
 *@return  = 0, 加密成功; = SECURE_ELEMENT_ERROR_BUF_SIZE, 数据为空
 *
 */

SecureElementStatus_t RBF_mac_payload_crypto(uint8_t *packet, uint32_t len,KeyIdentifier_t identifier)
{
#if defined (CONFIG_MACCRYPTO)
  uint8_t nonce[RBF_NONCE_LENGTH_MAX];
  uint8_t ad[RBF_AD_LENGTH_MAX];
  size_t plaintext_length;
  uint8_t ciphertext[255];
  size_t ciphertext_size=sizeof(ciphertext);
  size_t ciphertext_length;

  len = packet[0];

  if(packet == 0){
      return SECURE_ELEMENT_ERROR_BUF_SIZE;
  }
  uint32_t key_id = 0;

  //获取key_id
  if( RBF_get_key_id (identifier,&key_id) != SECURE_ELEMENT_SUCCESS){
      return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
  }
/*
 * nonce值获取
 *
 *
 */
#if defined (PACKET_0_INCLUDE)
  plaintext_length = packet[0]-RBF_MAC_PACKET_LEN_SIZE-RBF_HEADER_LENGTH_MAX-RBF_TAIL_LENGTH_MAX; //待加密的明文长度，不含CCM
#else //len = packet[0]
  plaintext_length = len-RBF_HEADER_LENGTH_MAX-RBF_TAIL_LENGTH_MAX; //待加密的明文长度，不含CCM
#endif
  RBF_payload_crypto_build_nonce (packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,nonce);
  RBF_payload_crypto_build_ad(packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,ad);

#if defined (CONFIG_LOG_MACCRYPTO)
  RBF_aes_param_log(nonce,ad,plaintext_length);
#endif
  DS_aes_ccm_use_keyid_ae(key_id,
                             nonce,
                             RBF_NONCE_LENGTH_MAX,
                             ad,
                             RBF_AD_LENGTH_MAX,
                             packet+RBF_MAC_HEADER_INDEX_LAST+1,
                             plaintext_length,
                             ciphertext,
                             ciphertext_size,
                             &ciphertext_length );




#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac origin data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif
// 赋值密文数据
  memcpy(packet+RBF_MAC_HEADER_INDEX_LAST+1,ciphertext,ciphertext_length);

#if defined (CONFIG_LOG_MACCRYPTO)

  DS_app_log_hexdump_debug("===mac payload crypto data: ",ciphertext,ciphertext_length);
#endif


#endif //end of CONFIG_MACCRYPTO

  return SECURE_ELEMENT_SUCCESS;
}

/*
 *
 *
 */
SecureElementStatus_t RBF_mac_payload_verify(uint8_t *packet,uint32_t len,KeyIdentifier_t identifier)
{
#if defined (CONFIG_MACCRYPTO)

  uint8_t nonce[RBF_NONCE_LENGTH_MAX];
  uint8_t ad[RBF_AD_LENGTH_MAX];
  uint8_t plaintext[255];

  size_t ciphertext_size,_out_len;/*plaintext_length,*/

  len = packet[0];

  if(packet == 0){
      return SECURE_ELEMENT_ERROR_BUF_SIZE;
  }
  uint32_t key_id = 0;

  //获取key_id
  if( RBF_get_key_id (identifier,&key_id) != SECURE_ELEMENT_SUCCESS){
      return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
  }

  /*
   *@note: TODO:通用协议密文的长度header是固定，可以通过以下方式进行计算。
   *@note: 特殊的cmd,由于协议不一样，需要进行特殊处理
   *
   */
#if defined (PACKET_0_INCLUDE)
  ciphertext_size = packet[0]-RBF_MAC_PACKET_LEN_SIZE-RBF_HEADER_LENGTH_MAX;
#else //len=packet[0]
  ciphertext_size = len-RBF_HEADER_LENGTH_MAX;
#endif

  RBF_payload_crypto_build_nonce (packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,nonce);
  RBF_payload_crypto_build_ad(packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,ad);
#if defined (CONFIG_LOG_MACCRYPTO)
  RBF_aes_param_log(nonce,ad,ciphertext_size);
#endif

  if(DS_aes_ccm_use_keyid_de(key_id,
                               nonce,
                               RBF_NONCE_LENGTH_MAX,
                               ad,
                               RBF_AD_LENGTH_MAX,
                               packet+RBF_MAC_HEADER_INDEX_LAST+1,
                               ciphertext_size,
                               plaintext,
                               sizeof(plaintext),
                               &_out_len) != 0){

      return SECURE_ELEMENT_FAIL_CCM;
  }


#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac crypto data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif

  //将加密的数据进行赋值
  memcpy(packet+RBF_MAC_HEADER_INDEX_LAST+1,plaintext,_out_len);

#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac origin data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif

#endif //end of CONFIG_MACCRYPTO
  return SECURE_ELEMENT_SUCCESS;
}
/*
 *@note 通过动态加载key，进行AES_CCM
 *
 */
SecureElementStatus_t RBF_mac_payload_crypto_dynamic_key(uint8_t *packet, uint32_t len,uint8_t *key)
{
#if defined (CONFIG_MACCRYPTO)
  uint8_t nonce[RBF_NONCE_LENGTH_MAX];
  uint8_t ad[RBF_AD_LENGTH_MAX];
  size_t plaintext_length;
  uint8_t ciphertext[255];
  size_t ciphertext_size=sizeof(ciphertext);
  size_t ciphertext_length;

  len = packet[0];

  if(packet == 0){
      return SECURE_ELEMENT_ERROR_BUF_SIZE;
  }
  uint32_t key_id = 0;
  DS_aes_ccm_dynamic_init(key,RBF_KEY_LENGTH_MAX);
  //获取key_id
  key_id = DS_aes_ccm_get_dynamic_key_id();

/*
 * nonce值获取
 *
 *
 */
#if defined (PACKET_0_INCLUDE)
  plaintext_length = packet[0]-RBF_MAC_PACKET_LEN_SIZE-RBF_HEADER_LENGTH_MAX-RBF_TAIL_LENGTH_MAX; //待加密的明文长度，不含CCM
#else //len=packet[0]
  plaintext_length = len-RBF_HEADER_LENGTH_MAX-RBF_TAIL_LENGTH_MAX; //待加密的明文长度，不含CCM
#endif
  RBF_payload_crypto_build_nonce (packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,nonce);
  RBF_payload_crypto_build_ad(packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,ad);

#if defined (CONFIG_LOG_MACCRYPTO)
  RBF_aes_param_log(nonce,ad,plaintext_length);
#endif
  DS_aes_ccm_use_keyid_ae(key_id,
                             nonce,
                             RBF_NONCE_LENGTH_MAX,
                             ad,
                             RBF_AD_LENGTH_MAX,
                             packet+RBF_MAC_HEADER_INDEX_LAST+1,
                             plaintext_length,
                             ciphertext,
                             ciphertext_size,
                             &ciphertext_length );




#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac origin data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif
// 赋值密文数据
  memcpy(packet+RBF_MAC_HEADER_INDEX_LAST+1,ciphertext,ciphertext_length);

#if defined (CONFIG_LOG_MACCRYPTO)

  DS_app_log_hexdump_debug("===mac payload crypto data: ",ciphertext,ciphertext_length);
#endif


#endif //end of CONFIG_MACCRYPTO

  return SECURE_ELEMENT_SUCCESS;
}
/*
 *@note 通过key进行aes-ccm 解密,key是16字节，128bitkey
 *
 */
SecureElementStatus_t RBF_mac_payload_verify_dynamic_key(uint8_t *packet,uint32_t len,uint8_t *key)
{
#if defined (CONFIG_MACCRYPTO)

  uint8_t nonce[RBF_NONCE_LENGTH_MAX];
  uint8_t ad[RBF_AD_LENGTH_MAX];
  uint8_t plaintext[255];

  size_t ciphertext_size,_out_len;/*plaintext_length*/

  len = packet[0];

  if(packet == 0){
      return SECURE_ELEMENT_ERROR_BUF_SIZE;
  }
  uint32_t key_id = 0;

  DS_aes_ccm_dynamic_init(key,RBF_KEY_LENGTH_MAX);
  //获取key_id
  key_id = DS_aes_ccm_get_dynamic_key_id();

  /*
   *@note: TODO:通用协议密文的长度header是固定，可以通过以下方式进行计算。
   *@note: 特殊的cmd,由于协议不一样，需要进行特殊处理
   *
   */
#if defined (PACKET_0_INCLUDE)
  ciphertext_size = packet[0]-RBF_MAC_PACKET_LEN_SIZE-RBF_HEADER_LENGTH_MAX;
#else //len=packet[0]
  ciphertext_size = len-RBF_HEADER_LENGTH_MAX;
#endif

  RBF_payload_crypto_build_nonce (packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,nonce);
  RBF_payload_crypto_build_ad(packet,RBF_MAC_PACKET_LEN_SIZE+RBF_HEADER_LENGTH_MAX,ad);
#if defined (CONFIG_LOG_MACCRYPTO)
  RBF_aes_param_log(nonce,ad,ciphertext_size);
#endif

  if(DS_aes_ccm_use_keyid_de(key_id,
                               nonce,
                               RBF_NONCE_LENGTH_MAX,
                               ad,
                               RBF_AD_LENGTH_MAX,
                               packet+RBF_MAC_HEADER_INDEX_LAST+1,
                               ciphertext_size,
                               plaintext,
                               sizeof(plaintext),
                               &_out_len) != 0){

      return SECURE_ELEMENT_FAIL_CCM;
  }


#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac crypto data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif

  //将加密的数据进行赋值
  memcpy(packet+RBF_MAC_HEADER_INDEX_LAST+1,plaintext,_out_len);

#if defined (CONFIG_LOG_MACCRYPTO)
  DS_app_log_hexdump_debug("===mac origin data: ",packet,packet[0]+PACKET_0_OUT_OFFSET);
#endif

#endif //end of CONFIG_MACCRYPTO
  return SECURE_ELEMENT_SUCCESS;
}

bool get_mac_key(uint8_t *packet,uint8_t *key)
{
  uint8_t cmd = 0;
  uint8_t id  = 0;

  cmd = packet[RBF_MAC_HEADER_INDEX_CMD];
  if(cmd == RBF_CMD_NODE_PAGING || cmd == RBF_CMD_GATEWAY_ALLOW_JOIN_NETWORK){//default1
      RBF_get_data_defaultKey1(key);
  }
  else if(cmd == RBF_CMD_NODE_ROAMING){//system
      RBF_get_data_systemKeyCode(key);//RBF_set_keyid_systemKeyCode(key);
  }
  else if(cmd == RBF_CMD_GATEWAY_SYNC_BROADCAST || cmd == RBF_CMD_GATEWAY_NOMAL_BROADCAST
      || cmd == RBF_CMD_NODE_FILE_TRANSFER_BLOCK
      || cmd == RBF_CMD_NODE_FILE_CHECK_REQ){//broadcast
      RBF_get_data_broadcastKeyCode(key);
  }
  else {//AB
#if defined (HUB_DEVICE)
      if(cmd==RBF_CMD_GATEWAY_ACK_EVENT || cmd==RBF_CMD_GATEWAY_ACK_HEARTBEAT || cmd==RBF_CMD_GATEWAY_DOWNLOAD){
          id = packet[RBF_MAC_HEADER_INDEX_DESTID];
      }
      else {
          id = packet[RBF_MAC_HEADER_INDEX_SRCID];
      }
      getNodeJoinCodeAB(key,id);
#endif
#if defined (RFM_DEVICE)
      RBF_get_data_codeAB(key);
#endif
  }
//  DS_app_log_error("key cmd=%d, id=%d, ",cmd,id);
//  DS_app_log_hexdump_error("key:",key,16);
  return true;
}
/*
 *
 *
 */
SecureElementStatus_t mac_payload_crypto(uint8_t *packet)
{
  SecureElementStatus_t ret = SECURE_ELEMENT_SUCCESS;
#if defined (CONFIG_MACCRYPTO)
  uint8_t key[RBF_KEY_LENGTH_MAX]={0};

  if(packet[0] == 0) return SECURE_ELEMENT_ERROR_BUF_SIZE;

  if(get_mac_key(packet,key)== false){
      return SECURE_ELEMENT_ERROR;
  }

  ret = RBF_mac_payload_crypto_dynamic_key(packet,16,key);
#endif
  return ret;
}
/*
 *
 *
 */
SecureElementStatus_t mac_payload_verify(uint8_t *packet)
{
  SecureElementStatus_t ret = SECURE_ELEMENT_SUCCESS;
#if defined (CONFIG_MACCRYPTO)
  uint8_t key[RBF_KEY_LENGTH_MAX]={0};

  if(packet[0] == 0) return SECURE_ELEMENT_ERROR_BUF_SIZE;

  if(get_mac_key(packet,key)== false){
      return SECURE_ELEMENT_ERROR;
  }

  ret = RBF_mac_payload_verify_dynamic_key(packet,16,key);
#endif
  return ret;
}
